﻿#include "FITKVAOneXMLWriter.h"
#include "FITKVAOneXMLIOInterface.h"
#include "rapidxml.hpp"
#include "rapidxml_print.hpp"
#include "FITK_Kernel/FITKAppFramework/FITKMessage.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaMaterial.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsFEModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscNodeList.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEAFace.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsSpectraManager.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsNCT.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsPhysicsProp.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsMaterial.h"
#include "VAOneXMLAdaptorNodes.h"
#include "VAOneXMLAdaptorSeaFacesPlate.h"
#include "VAOneXMLAdaptorSeaFacesSingleCurve.h"
#include "VAOneXMLAdaptorSeaFacesDoubleCurve.h"
#include "VAOneXMLAdaptorSeaPlateShell.h"
#include "VAOneXMLAdaptorSeaShellDoubleCurve.h"
#include "VAOneXMLAdaptorSeaShellSingleCurve.h"
#include "VAOneXMLAdaptorNCT.h"
#include "VAOneXMLAdaptorSeaBeam.h"
#include "VAOneXMLAdaptorSeaCavity.h"
#include "VAOneXMLAdaptorSinks.h"
#include "VAOneXMLAdaptorPowerSources.h"
#include "VAOneXMLAdaptorJunctions.h"
#include "VAOneXMLAdaptorConstraints.h"
#include "VAOneXMLAdaptorConnections.h"
#include "VAOneXMLAdaptorPhysicalProperty.h"
#include "VAOneXMLAdaptorSpectra.h"
#include "VAOneXMLAdaptorFrequencyDomain.h"
#include "VAOneXMLAdaptorMaterial.h"
#include "VAOneXMLAdaptorMaterialFE.h"
#include "VAOneXMLAdaptorFESubSystems.h"
#include "VAOneXMLAdaptorAcousticFESubSystems.h"
#include "VAOneXMLAdaptorFESubSystemElementList.h"

// 写出操作模板
template <typename T, typename S>
bool writeNodeData(T adaptor, rapidxml::xml_node<char>* node, S data)
{
    if (adaptor == nullptr) return false;
    adaptor->setDataObject(data);
    adaptor->setNode(node);
    bool ok = adaptor->adaptW();
    return ok;
}

// 获取管理器结构体
struct getManager
{
    Acoustics::FITKAcousticsSEASubSysManager* managerSEASubSystem;        ///< 子系统管理器
    Acoustics::FITKSEAFaceManager* managerSEAFace;                        ///< 面管理器
    Acoustics::FITKAcousticsMaterialManager* managerAcousticsMaterial;    ///< 声学材料管理器
    Interface::FITKMaterialManager* managerMaterial;                      ///< 材料管理器
}allManager;

bool initStruct()
{
    // 获取声学离散模型
    Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
    if (!discModel) return false;

    // 获取声学物理属性管理器
    Acoustics::FITKAcousticsPhysics* physics = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
    if (!physics) return false;

    // 初始化getManager结构体
    allManager.managerSEAFace = discModel->getSEAModel()->getSEAFaceManager();
    if (allManager.managerSEAFace == nullptr) return false;

    allManager.managerAcousticsMaterial = physics->getMaterialManager();
    if (allManager.managerAcousticsMaterial == nullptr) return false;

    allManager.managerSEASubSystem = discModel->getSEAModel()->getSEASubSysManager();
    if (allManager.managerSEASubSystem == nullptr) return false;

    allManager.managerMaterial = discModel->getFEModel()->getMaterialManager();
    if (allManager.managerMaterial == nullptr) return false;

    return true;
}

namespace VAOne
{
#if 1
    FITKVAOneXMLWriter::FITKVAOneXMLWriter(FITKVAOneXMLIOInterface* interface, bool & isScuccess)
        :_isSuccess(isScuccess),_compInterface(interface)
    {
        if (_compInterface == nullptr) return;
        _discModel = _compInterface->getDataObjectT<Acoustics::FITKAcousticsDiscModel>("Model");
        _physics = _compInterface->getDataObjectT<Acoustics::FITKAcousticsPhysics>("Physics");
    }

    void FITKVAOneXMLWriter::consoleMessage(int level, const QString& str)
    {
        switch (level)
        {
        case 1:AppFrame::FITKMessageNormal(str); break;
        case 2: AppFrame::FITKMessageWarning(str); break;
        case 3:AppFrame::FITKMessageError(str); break;
        default: AppFrame::FITKMessageError(str); break;
        }
    }
#endif // 构建

    void FITKVAOneXMLWriter::run()
    {
        if (_physics == nullptr || _discModel == nullptr) return;
        _document = new rapidxml::xml_document<char>();
       // if (!this->createContent()) return;
        // to do 
        if (_document == nullptr) return;
        
        _isSuccess = true;

        _isSuccess &= initStruct();
        if (_isSuccess != true) consoleMessage(3, QString("Get XML data fail."));

        // XML
        rapidxml::xml_node<>* xmlNode = _document->allocate_node(rapidxml::node_pi, "xml version=\"1.0\" encoding=\"UTF-8\"");
        if (xmlNode == nullptr) return;
        _document->append_node(xmlNode);

        // 模型
        rapidxml::xml_node<>* modelNode = _document->allocate_node(rapidxml::node_element, "Model");
        if (modelNode == nullptr) return;
        _document->append_node(modelNode);
        _isSuccess &= writeModel(modelNode);

        // 频率
        _isSuccess &= writeFrequencyDomain(modelNode);
        // Nodes
        _isSuccess &= writeNodes(modelNode);
        // 频谱
        _isSuccess &= writeSpectra(modelNode);
        // 材料
        _isSuccess &= writeMaterial(modelNode);
        // FE材料
        _isSuccess &= writeMaterialFE(modelNode);
        // 物理属性
        _isSuccess &= writePhysicalProp(modelNode);
        // 声学包
        _isSuccess &= writeAdaptorNCT(modelNode);
        // 面数据
        _isSuccess &= writeFaces(modelNode);
        // 子系统
        _isSuccess &= writeSubSystem(modelNode);
        // 半无限流体
        IO::VAOneXMLAdaptorSinks* adaptorSinks = nullptr;
        _isSuccess &= adaptorWrite<IO::VAOneXMLAdaptorSinks>("Sinks", adaptorSinks, modelNode);
        // 能量源
        IO::VAOneXMLAdaptorPowerSources* adaptorPowerSources = nullptr;
        _isSuccess &= adaptorWrite<IO::VAOneXMLAdaptorPowerSources>("PowerSources", adaptorPowerSources, modelNode);
        // 交点/耦合/连接
        IO::VAOneXMLAdaptorJunctions* adaptorJunctions = nullptr;
        _isSuccess &= adaptorWrite<IO::VAOneXMLAdaptorJunctions>("Junctions", adaptorJunctions, modelNode);
        // 约束
        IO::VAOneXMLAdaptorConstraints* adaptorConstraints = nullptr;
        _isSuccess &= adaptorWrite<IO::VAOneXMLAdaptorConstraints>("Constraints", adaptorConstraints, modelNode);
        // 连接
        IO::VAOneXMLAdaptorConnections* adaptorConnections = nullptr;
        _isSuccess &= adaptorWrite<IO::VAOneXMLAdaptorConnections>("Connections", adaptorConnections, modelNode);
        // FE部分
        _isSuccess &= writeFEData(modelNode);

        _isSuccess &= writeXML();

        if (!_isSuccess)
        {
            consoleMessage(3, QObject::tr("%1 Export Fail.").arg(_fileName));
        }
        else
        {
            consoleMessage(1, QObject::tr("%1 Export Success.").arg(_fileName));
        }
        
    }

    bool FITKVAOneXMLWriter::writeModel(rapidxml::xml_node<char>* node)
    {
        if (node == nullptr) return false;

        bool ok = true;

        ok &= writeAttribute(node, "xmlns", "http://www.esi-group.com/ns/VAOne");
        ok &= writeAttribute(node, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
        ok &= writeAttribute(node, "xsi:schemaLocation", "http://www.esi-group.com/ns/VAOne http://www.esi-group.com/xml/schemas/VAOne/2016/VAOne.xsd");
        ok &= writeAttribute(node, "name", "");
        ok &= writeAttribute(node, "note", "");

        // Version
        createNodeElement(node, "Version", "1.11.0.9");

        return ok;
    }

    bool FITKVAOneXMLWriter::writeNodes(rapidxml::xml_node<char> *modelNode)
    {
        if ((nullptr == modelNode) || (nullptr == modelNode->document())) return false;

        //获取节点管理器
        Acoustics::FITKAcousticsDiscNodeList *dataManager = _discModel->getNodes();
        if(nullptr == dataManager) return false;

        QList<int> listId;
        dataManager->getAllNodeID(listId);
        if (0 == listId.size()) return true;

        //开始写出节点
        consoleMessage(1, tr("Start writing Nodes."));

        rapidxml::xml_node<>* nodes = modelNode->document()->allocate_node(rapidxml::node_element, "Nodes");
        if (nullptr == nodes) return false;
        modelNode->append_node(nodes);

        // 获取节点读写适配器
        IO::VAOneXMLAdaptorNodes* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorNodes>("VAOneXML", dataManager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorNodes*, Acoustics::FITKAcousticsDiscNodeList*>(adaptor, nodes, dataManager);
        if (!ok) consoleMessage(3, QString("Write Nodes Error"));
        delete adaptor;
        return ok;
    }

#if 1
    bool FITKVAOneXMLWriter::writeFaces(rapidxml::xml_node<char> *modelNode)
    {
        if ((nullptr == modelNode) || (nullptr == modelNode->document())) return false;

        //获取FACE管理器
        Acoustics::FITKSEAFaceManager *dataManager = allManager.managerSEAFace;
        if (!dataManager) return false;
        if (0 == dataManager->getDataCount()) return true;

        rapidxml::xml_node<char>* facesNode = modelNode->document()->allocate_node(rapidxml::node_element, "Faces");
        if (nullptr == facesNode) return false;
        modelNode->append_node(facesNode);

        //开始写出面数据
        consoleMessage(1, tr("Start writing Faces."));

        bool bOK = true;

        bOK &= writeFacePlate(dataManager, facesNode);
        bOK &= writeFaceSingleCurve(dataManager, facesNode);
        bOK &= writeFaceDoubleCurve(dataManager, facesNode);

        return bOK;
    }
    bool FITKVAOneXMLWriter::writeFacePlate(Acoustics::FITKSEAFaceManager * manager, rapidxml::xml_node<char>* node)
    {
        if ((manager == nullptr) || (node == nullptr)) return false;

        // 获取平面读写适配器
        IO::VAOneXMLAdaptorSeaFacesPlate* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorSeaFacesPlate>("VAOneXMLFacePlate", manager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorSeaFacesPlate*, Acoustics::FITKSEAFaceManager*>(adaptor, node, manager);
        if (!ok) consoleMessage(3, QString("Write FacePlate Error"));
        delete adaptor;
        return ok;
    }
    bool FITKVAOneXMLWriter::writeFaceSingleCurve(Acoustics::FITKSEAFaceManager * manager, rapidxml::xml_node<char>* node)
    {
        if ((manager == nullptr) || (node == nullptr)) return false;

        // 获取单曲率面读写适配器
        IO::VAOneXMLAdaptorSeaFacesSingleCurve* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorSeaFacesSingleCurve>("VAOneXMLFaceSingleCurve", manager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorSeaFacesSingleCurve*, Acoustics::FITKSEAFaceManager*>(adaptor, node, manager);
        if (!ok) consoleMessage(3, QString("Write single curve face Error"));
        delete adaptor;
        return ok;
    }
    bool FITKVAOneXMLWriter::writeFaceDoubleCurve(Acoustics::FITKSEAFaceManager * manager, rapidxml::xml_node<char>* node)
    {
        if ((manager == nullptr) || (node == nullptr)) return false;

        // 获取双曲率面读写适配器
        IO::VAOneXMLAdaptorSeaFacesDoubleCurve* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorSeaFacesDoubleCurve>("VAOneXMLFaceDoubleCurve", manager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorSeaFacesDoubleCurve*, Acoustics::FITKSEAFaceManager*>(adaptor, node, manager);
        if (!ok) consoleMessage(3, QString("Write doubel curve face Error"));
        delete adaptor;
        return ok;
    }
    
#endif // 写入面数据

#if 1
    bool FITKVAOneXMLWriter::writeSubSystem(rapidxml::xml_node<char> *modelNode)
    {
        // 检查指针
        if ((nullptr == modelNode) || (nullptr == modelNode->document())) return false;

        //获取数据管理器
        Acoustics::FITKAcousticsSEASubSysManager *dataManager = allManager.managerSEASubSystem;
        if (!dataManager) return false;

        if (0 == dataManager->getDataCount()) return true;

        if (dataManager->getSubSysByType(Acoustics::FITKAbstractSEASubSys::SEABeam).isEmpty() &&
            dataManager->getSubSysByType(Acoustics::FITKAbstractSEASubSys::SEAFlatPlate).isEmpty() &&
            dataManager->getSubSysByType(Acoustics::FITKAbstractSEASubSys::SEASinglyCurvedShell).isEmpty() &&
            dataManager->getSubSysByType(Acoustics::FITKAbstractSEASubSys::SEADoublyCurvedShell).isEmpty() &&
            dataManager->getSubSysByType(Acoustics::FITKAbstractSEASubSys::SEACylinderShell).isEmpty() &&
            dataManager->getSubSysByType(Acoustics::FITKAbstractSEASubSys::SEACavity).isEmpty() &&
            dataManager->getSubSysByType(Acoustics::FITKAbstractSEASubSys::SEASemiIInfiniteFluid).isEmpty())
        {
            consoleMessage(2, QString("Subsystems don't have data."));
            return true;
        }

        // 添加<Subsystems>标签
        rapidxml::xml_node<char>* subSysNode = modelNode->document()->allocate_node(rapidxml::node_element, "Subsystems");
        if (nullptr == subSysNode) return false;
        modelNode->append_node(subSysNode);

        //开始写出子系统
        consoleMessage(1, tr("Start writing Subsystems."));

        // 初始化写入状态
        bool bOK = true;

        bOK &= writeSubSystemBeam(dataManager, subSysNode);
        bOK &= writeSubSystemFlatPlate(dataManager, subSysNode);
        bOK &= writeSubSystemSinglyCurvedShell(dataManager, subSysNode);
        bOK &= writeSubSystemDoublyCurvedShell(dataManager, subSysNode);
        bOK &= writeSubSystemCylinderShell(dataManager, subSysNode);
        bOK &= writeSubSystemCavity(dataManager, subSysNode);
        bOK &= writeSubSystemSemiIInfiniteFluid(dataManager, subSysNode);

        return bOK;
    }

    bool FITKVAOneXMLWriter::writeSubSystemBeam(Acoustics::FITKAcousticsSEASubSysManager * manager, rapidxml::xml_node<char>* node)
    {
        if ((manager == nullptr) || (node == nullptr)) return false;

        // 获取梁子系统读写适配器
        IO::VAOneXMLAdaptorSeaBeam* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorSeaBeam>("VAOneXMLBeam", manager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorSeaBeam*, Acoustics::FITKAcousticsSEASubSysManager*>(adaptor, node, manager);
        if (!ok) consoleMessage(3, QString("Write sub system Beam Error"));
        delete adaptor;
        return ok;
    }

    bool FITKVAOneXMLWriter::writeSubSystemFlatPlate(Acoustics::FITKAcousticsSEASubSysManager *manager, rapidxml::xml_node<char>* node)
    {
        if ((nullptr == node) || (nullptr == manager)) return false;

        // 获取平板子系统读写适配器
        IO::VAOneXMLAdaptorSeaPlateShell* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorSeaPlateShell>("VAOneXMLPlateShell", manager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorSeaPlateShell*, Acoustics::FITKAcousticsSEASubSysManager*>(adaptor, node, manager);
        if (!ok) consoleMessage(3, QString("Write sub system Flat Plate Error"));
        delete adaptor;
        return ok;
    }

    bool FITKVAOneXMLWriter::writeSubSystemSinglyCurvedShell(Acoustics::FITKAcousticsSEASubSysManager * manager, rapidxml::xml_node<char>* node)
    {
        if ((nullptr == node) || (nullptr == manager)) return false;

        // 获取单曲率板子系统读写适配器
        IO::VAOneXMLAdaptorSeaShellSingleCurve* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorSeaShellSingleCurve>("VAOneXMLSingleCurveShell", manager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorSeaShellSingleCurve*, Acoustics::FITKAcousticsSEASubSysManager*>(adaptor, node, manager);
        if (!ok) consoleMessage(3, QString("Write sub system Singly Curved Shell Error"));
        delete adaptor;
        return ok;
    }

    bool FITKVAOneXMLWriter::writeSubSystemDoublyCurvedShell(Acoustics::FITKAcousticsSEASubSysManager * manager, rapidxml::xml_node<char>* node)
    {
        if ((nullptr == node) || (nullptr == manager)) return false;

        // 获取双曲率板子系统读写适配器
        IO::VAOneXMLAdaptorSeaShellDoubleCurve* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorSeaShellDoubleCurve>("VAOneXMLDoubleCurveShell", manager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorSeaShellDoubleCurve*, Acoustics::FITKAcousticsSEASubSysManager*>(adaptor, node, manager);
        if (!ok) consoleMessage(3, QString("Write sub system Doubly Curved Shell Error"));
        delete adaptor;
        return ok;
    }

    bool FITKVAOneXMLWriter::writeSubSystemCylinderShell(Acoustics::FITKAcousticsSEASubSysManager * manager, rapidxml::xml_node<char>* node)
    {
        //if ((nullptr == node) || (nullptr == manager)) return false;
        //consoleMessage(3, QString("Write sub system Cylinder Shell Error."));
        return true;
    }

    bool FITKVAOneXMLWriter::writeSubSystemCavity(Acoustics::FITKAcousticsSEASubSysManager * manager, rapidxml::xml_node<char>* node)
    {
        if ((nullptr == node) || (nullptr == manager)) return false;

        // 获取声腔子系统读写适配器
        IO::VAOneXMLAdaptorSeaCavity* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorSeaCavity>("VAOneXMLCavity", manager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorSeaCavity*, Acoustics::FITKAcousticsSEASubSysManager*>(adaptor, node, manager);
        if (!ok) consoleMessage(3, QString("Write sub system Cavity Error"));
        delete adaptor;
        return ok;
    }

    bool FITKVAOneXMLWriter::writeSubSystemSemiIInfiniteFluid(Acoustics::FITKAcousticsSEASubSysManager * manager, rapidxml::xml_node<char>* node)
    {
        //if ((nullptr == node) || (nullptr == manager)) return false;
        //consoleMessage(3, QString("Write sub system SemiI Infinite Fluid Error"));
        return true;
    }
#endif // 写入SEA子系统数据

    bool FITKVAOneXMLWriter::writeMaterial(rapidxml::xml_node<char> *node)
    {
        if (node == nullptr) return false;

        rapidxml::xml_node<>* materialNode = _document->allocate_node(rapidxml::node_element, "Materials");
        if (nullptr == materialNode) return false;
        node->append_node(materialNode);

        Acoustics::FITKAcousticsMaterialManager* materialManager = _physics->getMaterialManager();
        if(!materialManager) return false;

        //开始写出材料
        consoleMessage(1, tr("Start writing Material."));

        // 获取材料读写适配器
        IO::VAOneXMLAdaptorMaterial* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorMaterial>("VAOneXML", materialManager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorMaterial*, Acoustics::FITKAcousticsMaterialManager*>(adaptor, materialNode, materialManager);
        if (!ok) consoleMessage(3, QString("Write Material Error"));
        delete adaptor;
        return ok;
    }

    bool FITKVAOneXMLWriter::writeMaterialFE(rapidxml::xml_node<char> *node)
    {
        if (node == nullptr) return false;

        Interface::FITKMaterialManager* manager = allManager.managerMaterial;
        if(!manager) return false;

        rapidxml::xml_node<>* materialFENode = _document->allocate_node(rapidxml::node_element, "FEMaterials");
        if (nullptr == materialFENode) return false;
        node->append_node(materialFENode);

        IO::VAOneXMLAdaptorMaterialFE* adaptor{};

        //开始写出材料
        consoleMessage(1, tr("Start writing FEMaterial."));

        bool ok = true;

        // 循环处理每个材料
        for (int i = 0; i < manager->getDataCount(); i++)
        {
            auto data = manager->getDataByIndex(i);
            if(nullptr == data) continue;

            Interface::FITKAbaMaterial* materialPtr = dynamic_cast<Interface::FITKAbaMaterial*>(data);
            if (nullptr == materialPtr) continue;

            if(nullptr == adaptor)
            {
                adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorMaterialFE>("VAOneXML", materialPtr);
                if (nullptr == adaptor) return false;
            }

            // 创建节点
            rapidxml::xml_node<char>* feNode = materialFENode->document()->allocate_node(rapidxml::node_element, "FEMaterial");
            if (nullptr == feNode) return false;
            materialFENode->append_node(feNode);
            adaptor->setDataObject(materialPtr);
            adaptor->setNode(feNode);

            // 执行数据写入
            ok &= adaptor->adaptW();
            if (!ok)
            {
                consoleMessage(3, QString("Write FEMaterial Error"));
                delete adaptor;
                return false;
            }
        }
        delete adaptor;
        // 返回操作是否成功
        return ok;
    }

    bool FITKVAOneXMLWriter::writeSpectra(rapidxml::xml_node<char> *node)
    {
        if (node == nullptr) return false;

        Acoustics::FITKAcousticsSpectraManager* spectraManager = _physics->getFITKAcousticsSpectraManager();
        if(!spectraManager) return false;

        rapidxml::xml_node<>* spectraNode = _document->allocate_node(rapidxml::node_element, "Spectra");
        if (nullptr == spectraNode) return false;
        node->append_node(spectraNode);

        //开始写出频谱
        consoleMessage(1, tr("Start writing Spectra."));

        // 获取频谱读写适配器
        IO::VAOneXMLAdaptorSpectra* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorSpectra>("VAOneXML", spectraManager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorSpectra*, Acoustics::FITKAcousticsSpectraManager*>(adaptor, spectraNode, spectraManager);
        if (!ok) consoleMessage(3, QString("Write Spectra Error"));
        delete adaptor;
        return ok;
    }

    bool FITKVAOneXMLWriter::writeFrequencyDomain(rapidxml::xml_node<char> *node)
    {
        if (node == nullptr) return false;

        Acoustics::FITKGlobalFrequencyDomain* frequencyDomainManager = _physics->getFrequencyDomain();
        if(!frequencyDomainManager) return false;

        rapidxml::xml_node<>* frequencyDomainNode = _document->allocate_node(rapidxml::node_element, "GlobalFrequencyDomain");
        if (nullptr == frequencyDomainNode) return false;
        node->append_node(frequencyDomainNode);

        //开始写出频率
        consoleMessage(1, tr("Start writing FrequencyDomain."));

        // 获取频率读写适配器
        IO::VAOneXMLAdaptorFrequencyDomain* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorFrequencyDomain>("VAOneXML", frequencyDomainManager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorFrequencyDomain*, Acoustics::FITKGlobalFrequencyDomain*>(adaptor, frequencyDomainNode, frequencyDomainManager);
        if (!ok) consoleMessage(3, QString("Write FrequencyDomain Error"));
        delete adaptor;
        return ok;
    }

    bool FITKVAOneXMLWriter::writePhysicalProp(rapidxml::xml_node<char> *node)
    {
        if (node == nullptr) return false;

        Acoustics::FITKAcousticsPhysicsPropManager* physicsPropManager = _physics->getPhysicsPropManager();
        if(!physicsPropManager) return false;

        rapidxml::xml_node<>* physicalPropNode = _document->allocate_node(rapidxml::node_element, "PhysicalProperties");
        if (nullptr == physicalPropNode) return false;
        node->append_node(physicalPropNode);

        //开始写出物理属性
        consoleMessage(1, tr("Start writing PhysicalProperties."));

        // 获取物理属性读写适配器
        IO::VAOneXMLAdaptorPhysicalProperty* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorPhysicalProperty>("VAOneXML", physicsPropManager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorPhysicalProperty*, Acoustics::FITKAcousticsPhysicsPropManager*>(adaptor, physicalPropNode, physicsPropManager);
        if (!ok) consoleMessage(3, QString("Write PhysicsProp Error"));
        delete adaptor;
        return ok;
    }

    bool FITKVAOneXMLWriter::writeAdaptorNCT(rapidxml::xml_node<char> *node)
    {
        if (node == nullptr) return false;

        Acoustics::FITKAcousticsNCTManager* nctManager = _physics->getFITKAcousticsNCTManager();
        if(!nctManager) return false;

        rapidxml::xml_node<>* nctNode = _document->allocate_node(rapidxml::node_element, "NoiseControlTreatments");
        if (nullptr == nctNode) return false;
        node->append_node(nctNode);

        //开始写出声学包
        consoleMessage(1, tr("Start writing NoiseControlTreatments."));

        // 获取声学包读写适配器
        IO::VAOneXMLAdaptorNCT* adaptor = FITKIOADAPTORFACTORY->createT<IO::VAOneXMLAdaptorNCT>("VAOneXML", nctManager);
        bool ok = writeNodeData<IO::VAOneXMLAdaptorNCT*, Acoustics::FITKAcousticsNCTManager*>(adaptor, nctNode, nctManager);
        if (!ok) consoleMessage(3, QString("Write nctManager Error"));
        delete adaptor;
        return ok;
    }

    bool FITKVAOneXMLWriter::writeFEData(rapidxml::xml_node<char>* node)
    {
        // Model节点
        if (node == nullptr) return false;

        bool ok = true;

        // 结构FE子系统
        IO::VAOneXMLAdaptorFESubSystems* adaptorFESubSystems = nullptr;
        ok &= adaptorWrite<IO::VAOneXMLAdaptorFESubSystems>("FESubsystems", adaptorFESubSystems, node);

        // 腔体FE子系统
        IO::VAOneXMLAdaptorAcousticFESubSystems* adaptorAcousticFESubSystems = nullptr;
        ok &= adaptorWrite<IO::VAOneXMLAdaptorAcousticFESubSystems>("AcousticFESubSystems", adaptorAcousticFESubSystems, node);

        // FE子系统单元列表
        IO::VAOneXMLAdaptorFESubSystemElementList* adaptorFESubSystemElementList = nullptr;
        ok &= adaptorWrite<IO::VAOneXMLAdaptorFESubSystemElementList>("FESubSystemElementList", adaptorFESubSystemElementList, node);

        return ok;
    }
    
    char * FITKVAOneXMLWriter::copyQStringToChar(const QString & qStr)
    {
        QByteArray utf8Bytes = qStr.toUtf8();
        int byteCount = utf8Bytes.size();
        char* cStr = new char[byteCount + 1];
        std::memcpy(cStr, utf8Bytes.constData(), byteCount);
        cStr[byteCount] = '\0';
        return cStr;
    }

    bool FITKVAOneXMLWriter::writeAttribute(rapidxml::xml_node<char>* node, QString attrName, QString value)
    {
        if (node == nullptr) return false;
        rapidxml::xml_attribute<>* attr = node->document()->allocate_attribute(copyQStringToChar(attrName),
            copyQStringToChar(value));
        node->append_attribute(attr);
        return true;
    }

    rapidxml::xml_node<char>* FITKVAOneXMLWriter::createNodeElement(rapidxml::xml_node<char>* parentNode, QString childName, QString value)
    {
        if (parentNode == nullptr) return  nullptr;
        rapidxml::xml_node<char>* newNode = parentNode->document()->allocate_node(rapidxml::node_element, copyQStringToChar(childName), copyQStringToChar(value));
        parentNode->append_node(newNode);
        return newNode;
    }
}
